﻿// 超速检测.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


/*
https://www.acwing.com/problem/content/6046/
https://www.luogu.com.cn/problem/P11232


小 D 新入职了某国的交管部门，他的第一个任务是负责国家的一条长度为 L 的南北主干道的车辆超速检测。

为了考考小 D，上司首先需要他解决一个简化的场景。

这个周末，主干道上预计出现 n 辆车，其中第 i 辆车从主干道上距离最南端 di 的位置驶入，
以 vi 的初速度和 ai的加速度做匀加速运动向北行驶。

我们只考虑从南向北的车辆，故 vi>0，但 ai 可正可负，也可以为零。

当车辆行驶到主干道最北端（即距离最南端为 L 的位置）或速度降为 0
（这只可能在 ai<0时发生）时，我们认为该车驶离主干道。

主干道上设置了 m 个测速仪，其中第 j 个测速仪位于主干道上距离最南端 pj的位置，每个测速仪可以设置开启或关闭。

当某辆车经过某个开启的测速仪时，若这辆车的瞬时速度超过了道路限速 V，那么这辆车就会被判定为超速。

注意当车辆驶入与驶出主干道时，如果在对应位置有一个开启的测速仪，这个测速仪也会对这辆车进行测速。

上司首先想知道，如果所有测速仪都是开启的，那么这 n 辆车中会有多少辆车被判定为超速。

其次，为了节能，部门想关闭一部分测速仪。

然而，他们不希望漏掉超速的车，也就是说，当 n辆车里的某辆车在所有测速仪都开启时被判定为超速，
他们希望在关闭一部分测速仪以后它依然被判定为超速。

上司还想知道在这样的条件下最多可以关闭多少测速仪。

由于 n 很大，上司允许小 D 使用编程解决这两个问题，于是小 D 找到了你。

如果你对于加速度并不熟悉，小 D 贴心地在本题的“提示”部分提供了有关加速度的公式。

输入格式
本题有多组测试数据。

输入的第一行包含一个正整数 T，表示数据组数。

接下来包含 T 组数据，每组数据的格式如下：

第一行包含四个整数 n,m,L,V，分别表示车辆数量、测速仪数量、主干道长度和道路限速。

接下来 n行：

第 i 行包含三个整数 di,vi,ai 描述一辆车。

最后一行包含 m 个整数 p1,p2,⋅⋅⋅,pm 描述道路上所有测速仪的位置。

输出格式
对于每组数据：输出一行包含两个整数，第一个整数为所有测速仪都开启时被判定为超速的车辆数量，第二个整数为在不漏掉超速车辆的前提下最多可以关闭的测速仪数量。

数据范围
对于所有测试数据，保证：

1≤T≤20；
1≤n,m≤105，1≤L≤106，1≤V≤103；
0≤di<L，1≤vi≤103，|ai|≤103；
0≤p1<p2<⋅⋅⋅<pm≤L。

特殊性质 A：保证 ai=0。
特殊性质 B：保证 ai>0。
特殊性质 C：保证 ai<0，且所有车都不在最北端驶离主干道。

输入样例：
1
5 5 15 3
0 3 0
12 4 0
1 1 4
5 5 -2
6 4 -4
2 5 8 9 15
输出样例：
3 3
样例解释
在该组测试数据中，主干道长度为 15，限速为 3，在距离最南端 2,5,8,9,15 的位置各设有一个测速仪。

第一辆车在最南端驶入，以 3 的速度匀速行驶。这辆车在整个路段上都没有超速。
第二辆车在距离最南端 12 的位置驶入，以 4的速度匀速行驶。在最北端驶离主干道时，
15 的测速仪判定为超速。
第三辆车在距离最南端 1 的位置驶入，以 1的初速度、4 的加速度行驶。
其在行驶了 32−122×4=1 的距离，即到达 2的位置时，速度变为 3
，并在之后一直超速。因此这辆车会被除了距离最南端 2的测速仪以外的其他测速仪判定为超速。
第四辆车在距离最南端 5 的位置驶入，以 5 的初速度、−2
 的加速度行驶。其在行驶了 32−522×(−2)=4 的距离，即到达 9的位置时，速度变为 3。
因此这辆车在距离最南端 [5,9) 时超速，会被距离最南端 5 和 8 的两个测速仪判定为超速。
第五辆车在距离最南端 6 的位置驶入，以 4的初速度、−4 的加速度行驶。
在其行驶了 32−422×(−4)=78 的距离后，即这辆车到达 678 的位置时，其速度变为 3
[6,678) 时超速，但这段区间内没有测速仪，因此不会被判定为超速。
因此第二、三、四辆车会被判定为超速，输出的第一个数为 3。

我们可以关闭距离最南端 2,8,9的三个测速仪，保留 5和 15的两个测速仪，此时三辆之前被判定为超速的车依然被判定为超速。

可以证明不存在更优方案，因此输出的第二个数为 3。

提示
与加速度有关的定义和公式如下：

匀加速运动是指物体在运动过程中，加速度保持不变的运动，即每单位时间内速度的变化量是恒定的。
当一辆车的初速度为 v0
、加速度 a≠0
，做匀加速运动，则 t
 时刻后它的速度 v1=v0+a×t
，它的位移（即行驶路程）s=v0×t+0.5×a×t2
。
当一辆车的初速度为 v0
、加速度 a≠0
，做匀加速运动，则当它的位移（即行驶路程）为 s
 时，这辆车的瞬时速度为 v20+2×a×s−−−−−−−−−−−√
。
当一辆车的初速度为 v0
、加速度 a≠0
，在它的位移（即行驶路程）为 v21−v202a
 时，这辆车的瞬时速度为 v1
。
如果你使用浮点数进行计算，需要注意潜在的精度问题。



1
5 5 15 99
0 3 0
12 4 0
1 1 4
5 5 -2
6 4 -4
2 5 8 9 15



20
10 10 175391 226
31181 234 -546
32757 670 -9
43723 775 -3
78541 862 -4
26626 961 -13
54690 759 -998
56165 659 -3
56531 776 -34
32860 950 -6
86709 145 47
31182 33025 46753 52673 57685 60635 99569 124240 162898 170704



20
9 10 134605 140
13933 958 -33
41957 532 -2
20334 813 -3
108114 954 -21
43406 882 -3
3891 868 -11
42207 847 -4
92899 350 -953
24555 857 -18
14622 27299 27606 35557 43791 48456 101617 112727 129152 129748


20
15 15 933700 276
498686 674 0
812487 587 0
98939 119 0
13940 776 0
268273 661 0
463457 729 0
590981 56 0
10961 688 0
340502 487 0
793685 862 0
332258 456 0
442210 751 0
453807 150 0
237248 136 0
242839 807 0
2 12 13 18 29 32 41 44 324728 324738 324741 324742 324754 324761 324762
*/

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

const int N = 100010;
int p[N];
int n, m, L, V;

struct CAR {
	int l, r;
	int d, v, a;
	bool operator<(const struct CAR& w)const {
		return r < w.r;
	}
}cars[N];

int ans1 = 0;

void check1(struct CAR& car) {
	p[0] = -1; p[m + 1] = 1000010;
	int l = 0; int r = m + 1;
	while (l < r) {
		int mid = l + r >> 1;
		if (p[mid] < car.d) {
			l = mid + 1;
		}
		else {
			int s = p[mid] - car.d;
			double currv = sqrt(1.0 * car.v * car.v + 2.0 * car.a * s);
			if (currv >= 1.0 * V)
				r = mid;
			else
				l = mid + 1;
		}
	}
	int s = p[l] - car.d;
	double currv = sqrt(1.0 * car.v * car.v + 2.0 * car.a * s);
	if (currv - 1.0 * V < 1e-8)
		l++;
	car.l = l; car.r = m;
	if (car.l > car.r) {
		car.l = -100; car.r = -100;
	}
	else {
		ans1++;
	}
}

void check2(struct CAR& car) {
	p[0] = -1; p[m + 1] = 1000010;
	int l = 1; int r = m + 1;
	while (l < r) {
		int mid = l + r >> 1;
		if (p[mid] < car.d) {
			l = mid + 1;
		}
		else {
			int s = p[mid] - car.d;
			double currv = sqrt(1.0 * car.v * car.v + 2.0 * car.a * s);
			if (1.0 * car.v * car.v + 2.0 * car.a * s < 0.0) {
				r = mid;
			}
			else {
				if (currv <= 1.0 * V) r = mid;
				else  l = mid + 1;
			}
		}
	}
	int s = p[l] - car.d;
	double currv = sqrt(1.0 * car.v * car.v + 2.0 * car.a * s);
	if (1.0 * car.v * car.v + 2.0 * car.a * s < 0 || currv <= 1.0 * V)
		l--;
	car.r = l;

	l = 1;  r = m + 1;
	while (l < r) {
		int mid = l + r >> 1;
		if (p[mid] >= car.d) r = mid;
		else l = mid + 1;
	}
	car.l = l;

	if (car.l > car.r) {
		car.l = -100; car.r = -100;
	}
	else {
		ans1++;
	}
	return;
}

void check0(struct CAR& car) {
	p[0] = -1; p[m + 1] = 1000010;
	if (car.v > V && car.d <= p[m]) {
		car.r = m;
		int l = 0; int r = m + 1;
		while (l < r) {
			int mid = l + r >> 1;
			if (p[mid] >= car.d) r = mid;
			else l = mid + 1;
		}
		car.l = l;
		ans1++;
	}
	else {
		car.l = -100; car.r = -100;
	}
}

void solve() {
	ans1 = 0;
	memset(cars, 0, sizeof cars);
	memset(p, 0, sizeof p);
	//cin >> n >> m >> L >> V;
	scanf("%d%d%d%d",&n,&m,&L,&V);

	for (int i = 1; i <= n; i++) {
		//cin >> cars[i].d >> cars[i].v >> cars[i].a;
		scanf("%d%d%d",&cars[i].d, &cars[i].v, &cars[i].a);
	}

	for (int i = 1; i <= m; i++) {
		//cin >> p[i];
		scanf("%d",&p[i]);
	}
	//34762 v = 276
	for (int i = 1; i <= n; i++) {
		if (cars[i].a == 0) {
			check0(cars[i]);
		}
		else if (cars[i].a > 0) {
			check1(cars[i]);
		}
		else {
			check2(cars[i]);
		}
	}

	//区间相交
	sort(cars + 1, cars + 1 + n);
	int res = 0; int ed = -1;
	for (int i = 1; i <= n; i++) {
		if (cars[i].l > ed) {
			res++;
			ed = cars[i].r;
		}
	}

	//cout << ans1 << " " << m - res << endl;
	printf("%d %d\n",ans1,m-res);

	return;
}


int main()
{
	int T; 
	//cin >> T;
	scanf("%d",&T);
	while (T--) {
		solve();
	}

	return 0;
}

